//SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
//SPDX-License-Identifier: GPL-3.0-only

package board_draw_api_serv

import (
	"context"
	"time"

	"gitcode.com/eteam/api-server/dao"
	"gitcode.com/eteam/api-server/dao/board_dao"
	"gitcode.com/eteam/api-server/notice_serv"
	"gitcode.com/eteam/proto-gen-go.git/board_draw_api"
	"gitcode.com/eteam/proto-gen-go.git/notices/notices_board"
	"github.com/google/uuid"
	"go.mongodb.org/mongo-driver/mongo"
)

func (apiImpl *BoardDrawApiImpl) CreateDraw(ctx context.Context, req *board_draw_api.CreateDrawRequest) (*board_draw_api.CreateDrawResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.CreateDrawResponse{
			Code:   board_draw_api.CreateDrawResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.CreateDrawResponse{
			Code:   board_draw_api.CreateDrawResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_draw_api.CreateDrawResponse{
			Code:   board_draw_api.CreateDrawResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	drawId := uuid.NewString()
	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.DrawInfoDao.Insert(sessCtx, &board_dao.DrawInfoDbItem{
			DrawId:  drawId,
			BoardId: req.BoardId,
			BasicInfo: board_dao.BasicDrawInfoDbItem{
				DrawName: req.BasicInfo.DrawName,
			},
			EditMemberUserIdList: []string{},
			NodeCount:            0,
			EdgeCount:            0,
			CreateTime:           nowTime,
			UpdateTime:           nowTime,
			LastChatTime:         nowTime,
		})
		if err != nil {
			return nil, err
		}

		return &board_draw_api.CreateDrawResponse{
			Code:   board_draw_api.CreateDrawResponse_CODE_OK,
			DrawId: drawId,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.CreateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  drawId,
	})
	return ret.(*board_draw_api.CreateDrawResponse), nil
}

func (apiImpl *BoardDrawApiImpl) UpdateDrawBasic(ctx context.Context, req *board_draw_api.UpdateDrawBasicRequest) (*board_draw_api.UpdateDrawBasicResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.UpdateDrawBasicResponse{
			Code:   board_draw_api.UpdateDrawBasicResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.UpdateDrawBasicResponse{
			Code:   board_draw_api.UpdateDrawBasicResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_draw_api.UpdateDrawBasicResponse{
			Code:   board_draw_api.UpdateDrawBasicResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//检查画稿是否存在
	exist, err := board_dao.DrawInfoDao.Exist(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_draw_api.UpdateDrawBasicResponse{
			Code:   board_draw_api.UpdateDrawBasicResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.DrawInfoDao.UpdateBasic(sessCtx, req.BoardId, req.DrawId, &board_dao.BasicDrawInfoDbItem{
			DrawName: req.BasicInfo.DrawName,
		}, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.UpdateDrawBasicResponse{
			Code: board_draw_api.UpdateDrawBasicResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	return ret.(*board_draw_api.UpdateDrawBasicResponse), nil
}

func (apiImpl *BoardDrawApiImpl) UpdateDrawEditMember(ctx context.Context, req *board_draw_api.UpdateDrawEditMemberRequest) (*board_draw_api.UpdateDrawEditMemberResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.UpdateDrawEditMemberResponse{
			Code:   board_draw_api.UpdateDrawEditMemberResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.UpdateDrawEditMemberResponse{
			Code:   board_draw_api.UpdateDrawEditMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_draw_api.UpdateDrawEditMemberResponse{
			Code:   board_draw_api.UpdateDrawEditMemberResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	//检查画稿是否存在
	exist, err := board_dao.DrawInfoDao.Exist(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_draw_api.UpdateDrawEditMemberResponse{
			Code:   board_draw_api.UpdateDrawEditMemberResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
		}, nil
	}
	//检查成员是否存在
	existMemberUserIdList, err := board_dao.MemberInfoDao.DistinctMemberUserId(ctx, req.BoardId, true, req.EditMemberUserIdList)
	if err != nil {
		return nil, err
	}
	if len(existMemberUserIdList) != len(req.EditMemberUserIdList) {
		return &board_draw_api.UpdateDrawEditMemberResponse{
			Code:   board_draw_api.UpdateDrawEditMemberResponse_CODE_NO_MEMBER,
			ErrMsg: "画板成员不存在",
		}, nil
	}

	nowTime := time.Now().UnixMilli()

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		err = board_dao.DrawInfoDao.UpdateEditMemberUserIdList(sessCtx, req.BoardId, req.DrawId, req.EditMemberUserIdList, nowTime)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.UpdateDrawEditMemberResponse{
			Code: board_draw_api.UpdateDrawEditMemberResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.UpdateDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	return ret.(*board_draw_api.UpdateDrawEditMemberResponse), nil
}

func (apiImpl *BoardDrawApiImpl) RemoveDraw(ctx context.Context, req *board_draw_api.RemoveDrawRequest) (*board_draw_api.RemoveDrawResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.RemoveDrawResponse{
			Code:   board_draw_api.RemoveDrawResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}

	//检查权限
	memberItem, err := board_dao.MemberInfoDao.Get(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return &board_draw_api.RemoveDrawResponse{
			Code:   board_draw_api.RemoveDrawResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}
	if !(memberItem.Admin) {
		return &board_draw_api.RemoveDrawResponse{
			Code:   board_draw_api.RemoveDrawResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	dbSess, err := dao.StartSession()
	if err != nil {
		return nil, err
	}
	defer dao.EndSession(dbSess)

	ret, err := dbSess.WithTransaction(ctx, func(sessCtx mongo.SessionContext) (interface{}, error) {
		//删除所有节点
		err = board_dao.NodeInfoDao.RemoveByDraw(sessCtx, req.BoardId, req.DrawId)
		if err != nil {
			return nil, err
		}
		//删除所有边
		err = board_dao.EdgeInfoDao.RemoveByDraw(sessCtx, req.BoardId, req.DrawId)
		if err != nil {
			return nil, err
		}
		err = board_dao.DrawInfoDao.Remove(sessCtx, req.BoardId, req.DrawId)
		if err != nil {
			return nil, err
		}
		return &board_draw_api.RemoveDrawResponse{
			Code: board_draw_api.RemoveDrawResponse_CODE_OK,
		}, nil
	})
	if err != nil {
		return nil, err
	}
	//发送通知
	go notice_serv.PublishToBoard(req.BoardId, &notices_board.RemoveDrawNotice{
		BoardId: req.BoardId,
		DrawId:  req.DrawId,
	})
	return ret.(*board_draw_api.RemoveDrawResponse), nil
}

func (apiImpl *BoardDrawApiImpl) ListDraw(ctx context.Context, req *board_draw_api.ListDrawRequest) (*board_draw_api.ListDrawResponse, error) {
	emptyList := []*board_draw_api.DrawInfo{}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.ListDrawResponse{
			Code:     board_draw_api.ListDrawResponse_CODE_WRONG_SESSION,
			ErrMsg:   "会话不存在",
			DrawList: emptyList,
		}, nil
	}

	//检查权限
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_draw_api.ListDrawResponse{
			Code:     board_draw_api.ListDrawResponse_CODE_NO_PERMISSION,
			ErrMsg:   "没有权限",
			DrawList: emptyList,
		}, nil
	}

	count, err := board_dao.DrawInfoDao.CountByBoard(ctx, req.BoardId)
	if err != nil {
		return nil, err
	}
	drawItemList, err := board_dao.DrawInfoDao.ListByBoard(ctx, req.BoardId, req.OrderBy, int64(req.Offset), int64(req.Limit))
	if err != nil {
		return nil, err
	}
	//生成结果
	drawList := []*board_draw_api.DrawInfo{}
	for _, drawItem := range drawItemList {
		draw := drawItem.ToDrawInfo()
		drawList = append(drawList, draw)
	}
	return &board_draw_api.ListDrawResponse{
		Code:       board_draw_api.ListDrawResponse_CODE_OK,
		TotalCount: count,
		DrawList:   drawList,
	}, nil
}

func (apiImpl *BoardDrawApiImpl) GetDraw(ctx context.Context, req *board_draw_api.GetDrawRequest) (*board_draw_api.GetDrawResponse, error) {
	emptyInfo := &board_draw_api.DrawInfo{
		BasicInfo: &board_draw_api.BasicDrawInfo{},
	}

	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.GetDrawResponse{
			Code:   board_draw_api.GetDrawResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
			Draw:   emptyInfo,
		}, nil
	}

	//检查权限
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_draw_api.GetDrawResponse{
			Code:   board_draw_api.GetDrawResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
			Draw:   emptyInfo,
		}, nil
	}

	drawItem, err := board_dao.DrawInfoDao.Get(ctx, req.BoardId, req.DrawId)
	if err != nil {
		return &board_draw_api.GetDrawResponse{
			Code:   board_draw_api.GetDrawResponse_CODE_NO_DRAW,
			ErrMsg: "画稿不存在",
			Draw:   emptyInfo,
		}, nil
	}
	draw := drawItem.ToDrawInfo()
	return &board_draw_api.GetDrawResponse{
		Code: board_draw_api.GetDrawResponse_CODE_OK,
		Draw: draw,
	}, nil
}

func (apiImpl *BoardDrawApiImpl) ReportMousePosition(ctx context.Context, req *board_draw_api.ReportMousePositionRequest) (*board_draw_api.ReportMousePositionResponse, error) {
	sessItem, ok := dao.CacheDao.GetSession(ctx, req.SessionId)
	if !ok {
		return &board_draw_api.ReportMousePositionResponse{
			Code:   board_draw_api.ReportMousePositionResponse_CODE_WRONG_SESSION,
			ErrMsg: "会话不存在",
		}, nil
	}
	exist, err := board_dao.MemberInfoDao.Exist(ctx, req.BoardId, sessItem.UserId)
	if err != nil {
		return nil, err
	}
	if !exist {
		return &board_draw_api.ReportMousePositionResponse{
			Code:   board_draw_api.ReportMousePositionResponse_CODE_NO_PERMISSION,
			ErrMsg: "没有权限",
		}, nil
	}

	notice_serv.PublishToBoard(req.BoardId, &notices_board.UserMouseChangeNotice{
		BoardId:      req.BoardId,
		DrawId:       req.DrawId,
		MemberUserId: sessItem.UserId,
		X:            req.X,
		Y:            req.Y,
	})

	return &board_draw_api.ReportMousePositionResponse{
		Code: board_draw_api.ReportMousePositionResponse_CODE_OK,
	}, nil
}
